package xyz.thoughtset.viewer.common.crud.api.factory;

import xyz.thoughtset.viewer.common.crud.core.annotation.ApiCRUDPower;
import xyz.thoughtset.viewer.common.crud.core.service.BaseService;
import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

@Component
public class CrudApiPowerMgtFactory {
    @Value("${scan.package}")
    private String scanPackage;

    @Autowired
    protected ApplicationContext applicationContext;

    private Map<String, ApiCRUDPower> powerCheckMap = new HashMap<>();

    @PostConstruct
    public void init() {
        // 创建扫描器，false 表示不检查父类
        ClassPathScanningCandidateComponentProvider scanner =
                new ClassPathScanningCandidateComponentProvider(false);
        scanner.addIncludeFilter(new AnnotationTypeFilter(ApiCRUDPower.class));
        // 扫描指定包
        Set<BeanDefinition> beanDefinitions = scanner.findCandidateComponents(scanPackage);
        for (BeanDefinition beanDefinition : beanDefinitions) {
            try {
                Class<?> clazz = Class.forName(beanDefinition.getBeanClassName());
                String key = StringUtils.uncapitalize(clazz.getSimpleName());
                powerCheckMap.put(key,clazz.getAnnotation(ApiCRUDPower.class));
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    }
    public BaseService targetService(String key,boolean wasCmd){
        ApiCRUDPower power = powerCheckMap.get(key);
        Class serverClass = null;
        if (Objects.nonNull(power)){
            serverClass = wasCmd ? power.cmdServiceClass():power.queryServiceClass();
        }
        BaseService targetService;
        if (Objects.isNull(serverClass)) return null;
        if (!BaseService.class.equals(serverClass)) {
            targetService = (BaseService) applicationContext.getBean(serverClass);
        }else{
            targetService = (BaseService) applicationContext.getBean(key + "ServiceImpl");
        }
        return targetService;
    }

    public boolean checkPower(String name, String methodName,boolean wasCmd){
        boolean flag = false;
        ApiCRUDPower power = powerCheckMap.get(name);
        if (Objects.isNull(power)) return false;
        switch (methodName){
            case "insert" : flag = power.insert(); break;
            case "save" : flag = power.save(); break;
            case "update" : flag = power.update(); break;
            case "replace" : flag = power.replace(); break;
            case "delete" : flag = power.delete(); break;
            case "removeList" : flag = power.removeList(); break;
            case "one" : flag = power.one(); break;
            case "list" : flag = power.list(); break;
            case "page" : flag = power.page(); break;
            default: throw new RuntimeException("Unknown method"+methodName);
        }
        if (wasCmd && flag){
            flag = !power.searchOnly();
        }
        return flag;
    }

}
